package com.java.base.exercise.refelction;

import com.java.base.exercise.annonation.Common;
import com.java.base.exercise.annonation.Knowledge;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import javax.smartcardio.CommandAPDU;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @Author RenPu
 * @Date 2023/10/3 15:28
 * @Version 1.0
 * @Description: 反射功能的运用
 **/

@Slf4j
public class Reflection {


    public static void main(String[] args) throws Exception {

        //方式1：通过反射获取类名，包名
        Common common = new Common();
        Class<? extends Common> acls = common.getClass(); //通过反射获取类的元信息

        //方式2：通过反射获取类名，包名
        Class<?> acls1 = Class.forName("com.java.base.exercise.annonation.Common");   //通过反射获取类的元信息
//        Object o = acls1.newInstance();
        log.info("获取类名+包名：：：：："+acls);
        log.info("获取类名+包名：：：：："+acls1);
        log.info("获取类名：：：：："+acls1.getSimpleName());
        Object o = acls1.newInstance();
        //通过反射获取类得属性
        Field[] fields = acls.getDeclaredFields();
        for (Field field : fields) {
            log.info("类得属性：：："+field);
        }

        //通过反射获取类属性对应得值
        common.setName("不良帅");
        common.setAddress("大唐盛世");
        for (Field field : fields) {
            field.setAccessible(true);   //设置属性得可见性, 对属性的获取和赋值都需要进行设置可见性
            log.info("类得属性：：："+field.get(common));
        }


        //通过反射进行实例化对象，对对象的属性值进行赋值
        Object common1 = acls.newInstance();
        for (Field field : fields) {
            field.setAccessible(true);
            if(field.getName().equals("name")){
                field.set(common1,"反射实例化赋值：：不良帅");
            }else {
                field.set(common1,"反射实例化赋值：：大唐盛世");
            }
        }

        log.info(common1.toString());
        
        //通过反射获取类中的方法

        Method[] methods = Common.class.getDeclaredMethods();
        for (Method method : methods) {
            if(method.getName().equals("getRich")){
                method.setAccessible(true);
                log.info("反射获取类中的方法:::"+method.getName());

            }

        }

        //通过反射调用私有修饰的方法进行执行
        Method method = acls.getDeclaredMethod("getRich");
        method.setAccessible(true);
        Object invoke = method.invoke(common);
        log.info("通过反射调用私有修饰的方法，执行的Result"+invoke);


        //反射结合注解得运用
        //1：获取类上得注解
        Knowledge annotation = acls.getAnnotation(Knowledge.class);
        String name = annotation.name();
        String[] meters = annotation.meters();
        for (String meter :meters) {
            log.info("获取类上得注解得内容"+meter);
        }
        log.info("获取类上得注解得内容：：："+name);

        //2: 获取类中方法上得注解
        for (Method method1 : methods) {
            Knowledge annotation1 = method1.getAnnotation(Knowledge.class);
            if(Objects.isNull(annotation1)) continue;
            String name1 = annotation1.name();
            String[] meters1 = annotation1.meters();
            for (String s : meters1) {
                log.info("获取类中方法上得注解的内容:::: meters1 "+s);

            }
            log.info("获取类中方法上得注解的内容 :::::"+name1);


        }

        //3: 获取类中属性上得注解
        for (Field field : fields) {
            Knowledge fieldAnnotation = field.getAnnotation(Knowledge.class);
            if(Objects.isNull(fieldAnnotation)) continue;

            String name1 = fieldAnnotation.name();
            String[] meters1 = fieldAnnotation.meters();
            for (String s : meters1) {
                log.info("获取类中属性上得注解的内容:::: meters1 "+s);

            }
            log.info("获取类中属性上得注解的内容 :::::"+name1);
        }

    }


}
